function EditorPanel(doc) {
	EditorPanel._super.call(this, "edit", doc);
	this._editorWnd = window;
	this.element.style.left = "55%";
	this.element.style.top = "60%";
	// editor form
	this.form = this.doc.doc.createElement("form");
	this.form.style.margin = "0px";
	this.form.style.padding = "0px";
	this._editor = this.doc.doc.createElement("div");
	this.form.appendChild(this._editor);
	this.form._updateAction = null;
	this.form._panel = this;
	new EventListener(this.form, "submit", function(evn) {
			try {
				if (this._updateAction) {
					this._updateAction.entityView = this._panel._loadedEntityView;
					this._updateAction.form = this;
					this._updateAction.perform();
				}
			}
			finally {
				return EventListener.cancelEvent(evn);
			}
		});
	this.form.selectFirstInput = function() {
		var elements = this.getElementsByTagName("*");
		for (var i = 0; i < elements.length; ++i) {
			var e = elements[i];
			if (e.className == "richtext_input") {
				if (e.iframe) {
					e.iframe.contentWindow.focus();
					e.iframe._select = true;
				}
				else {
					e.focus();
					e.ownerDocument.execCommand("selectall", false, null);
				}
				return;
			}
			else if (EditorPanel.isActiveContentElement(e)) {
				e.focus();
				e.select && e.select();
				return;
			}
		}
	};
	this.element.appendChild(this.form);
	this.element._panel = this;
	new EventListener(this.element, "keydown", function(evn) {
			this._panel.onKey(evn);
		});
}
Object.extend("EditorPanel", "WindowPanel");

EditorPanel.prototype.onKey = function(evn) {
	if (evn.ctrlKey && !evn.altKey && (evn.keyCode == 13)) { // Ctrl-Enter
		this.form._updateAction.entityView = this._loadedEntityView;
		this.form._updateAction.form = this.form;
		this.form._updateAction.perform();
		return EventListener.cancelEvent(evn);
	}
	else if ((evn.keyCode == 38) || (evn.keyCode == 40)) { // arrow up/down
		var e = evn.target;
		if (e.type == "text") {
			if (browser.isGecko) {
				// quick inc/dec number inputs
				var val = e.value;
				var selStart = e.selectionStart;
				var selEnd = e.selectionEnd;
				// determine all the digits
				var num = Number.NaN
				var i;
				for (i = selEnd - 1; i >= 0; --i) {
					var str = val.substring(i, selEnd);
					if (str.charAt(0) == ' ')
						break;
					var n = Number(str);
					if (isNaN(n))
						break;
					num = n;
				}
				if (!isNaN(num)) {
					e.value = val.substring(0, i + 1) + ((evn.keyCode == 38)?num + 1:num - 1)
						+ val.substring(selEnd);
					e.selectionStart = selStart;
					e.selectionEnd = selEnd;
					return EventListener.cancelEvent(evn);
				}
			}
			else {
				// TODO: implement quick inc/dec in IE
				var sel = this.ownerDocument.selection;
				var r = sel.createRange();
				r.select();
			}
		}
	}
}

EditorPanel.prototype.resize = function(diffX, diffY) {
	var eX = Dom(this._editor).getElementsByClassName("ed_body")[0];
	if (!eX)
		eX = this._editor;
	var eY = this._dynHeight;
	if (!eY)
		eY = eX;
	var w1 = eX.offsetWidth;
	var h1 = eY.offsetHeight;
	var w = diffX + eX.offsetWidth;
	var h = diffY + eY.offsetHeight;
	eX.style.width = ((w > 0)?w:1) + "px";
	eY.style.height = ((h > 0)?h:1) + "px";
	EditorPanel._super.prototype.resize.call(this, eX.offsetWidth - w1, eY.offsetHeight - h1);
}

EditorPanel.prototype.setEntityView = function(entityView) {
	this._entityView = entityView;
	if (this.isOpen)
		this.loadEntity();
}

EditorPanel.prototype.open = function(editorKey, action) {
	this.form._updateAction = (action)?action:new UpdateAction("update", "Update", this._entityView);
	this._editorKey = editorKey;
	EditorPanel._super.prototype.open.call(this);
	this.loadEntity();
}

EditorPanel.prototype.loadEntity = function() {
	if (!this._entityView)
		return;
	if (this._entityView != this._loadedEntityView) {
		this.header.innerHTML = this._entityView.getActiveEntityPath();
		var self = this;
		this._entityView.entity.load(function() {
				self.form._updateAction.reset();
				this.fillEditor(self.header, self._editor, self._editorKey);
				self.element.style.height = null;
				self.buildInputs();
				// try to pre-select
				try {
					self.form.selectFirstInput();
				}
				catch (ex) {
				}
			});
		this._loadedEntityView = this._entityView;
	}
	else {
		this.form.selectFirstInput();
	}
}

EditorPanel.isActiveContentElement = function(e) {
	return e.name && (e.name.indexOf("content") == 0) && e.type && (e.type != "hidden")
		&& (!e.style || (e.style.display != "none"));
}

EditorPanel.prototype.hasInputChanged = function() {
	if ("initial" != this.form._updateAction.state)
		return false;
	var elements = this._editor.getElementsByTagName("*");
	for (var i = 0; i < elements.length; ++i) {
		var e = elements[i];
		if (e._hasInputChanged && e._hasInputChanged())
			return true;
		else if (EditorPanel.isActiveContentElement(e) && (e.value != e._originalContent))
			return true;
	}
	return false;
}

EditorPanel.prototype.buildInputs = function() {
	var elements = this._editor.getElementsByTagName("*");
	for (var i = 0; i < elements.length; ++i) {
		var e = elements[i];
		if (e.className == "richtext_input")
			this.buildRichTextEditor(e);
		else if (e.className == "dateTime_input")
			new DateTimeInput(e.firstChild);
		else if (e.className == "date_input")
			new DateInput(e.firstChild);
		else if (e.className == "ref_input")
			new RefAutoCompleteInput(e.firstChild, this._entityView.objId);
		if (EditorPanel.isActiveContentElement(e))
			e._originalContent = e.value;
	}
	var doc = this._editor.ownerDocument;
	var rtTb = doc.getElementById("_richtextToolbar");
	if (rtTb) {
		this.richtextToolbar = new RichtextToolbar(rtTb);
		this.richtextToolbar._panel = this;
		this.richtextToolbar.execCmd = function(cmd) {
			this._panel._editorWnd.focus();
			if (this._panel._currentEdit)
				this._panel._currentEdit.focus();
			var arg = null;
			if (cmd == "createlink")
				arg = "#";
			this._panel._editorWnd.document.execCommand(cmd, false, arg);
		};
		this.richtextToolbar.addButton("Bold (Ctrl-Shift-B)", 19, "bold");
		this.richtextToolbar.addButton("Italic (Ctrl-Shift-I)", 20, "italic");
		this.richtextToolbar.addButton("Underline (Ctrl-Shift-U)", 21, "underline");
		this.richtextToolbar.addButton("Strike Through (Ctrl-Shift-K)", 22, "strikethrough");
		this.richtextToolbar.addButton("Subscript (Ctrl-Shift-D)", 23, "subscript");
		this.richtextToolbar.addButton("Superscript (Ctrl-Shift-P)", 24, "superscript");
		this.richtextToolbar.addButton("Remove Format (Ctrl-Shift-R)", 18, "removeFormat");
		this.richtextToolbar.addButton("Create Link (Ctrl-Shift-L)", 33, "createlink");
		this.richtextToolbar.addButton("Unlink (Ctrl-Shift-N)", 34, "unlink");
	}
}

EditorPanel.prototype.buildRichTextEditor = function(element) {
	element._originalContent = element.innerHTML;
	if (typeof element.contentEditable != "undefined") {
		this._dynHeight = element;
		element._panel = this;
		element.contentEditable = true;
		if (browser.isGeko)
			element.ownerDocument.execCommand("styleWithCSS", false, false);
		new EventListener(element, "keydown", this.onRichTextKey);
		element._hasInputChanged = function() {
			return this.innerHTML != this._originalContent;
		}
		element._wnd = window;
		new EventListener(element, "focus", function(evn) {
				this._panel._currentEdit = this;
				if (this._wnd._tmpHideTimerId) {
					this._wnd.clearTimeout(this._wnd._tmpHideTimerId);
					this._wnd._tmpHideTimerId = null;
				}
				this._panel.richtextToolbar.show();
			});
		new EventListener(element, "blur", function(evn) {
				this._wnd._tmpHide = this._panel.richtextToolbar;
				if (this._wnd._tmpHideTimerId)
					this._wnd.clearTimeout(this._wnd._tmpHideTimerId);
				this._wnd._tmpHideTimerId = this._wnd.setTimeout(function() {
						this._tmpHide.hide();
						this._tmpHide = null;
					}, 500);
			});
	}
	else {
		var f = this.doc.doc.createElement("iframe");
		// f.setAttribute("tabIndex", "1");
		f.setAttribute("height", "auto");
		f.setAttribute("width", "100%");
		f.setAttribute("frameborder", "0", false);
		f.setAttribute("vspace", "0", false);
		f.data = element.innerHTML;
		f._panel = this;
		f._wnd = window;
		new EventListener(f, "load", function(evn) {
				var doc = this.contentWindow.document;
				doc.head = doc.documentElement.getElementsByTagName("head")[0];
				doc.head.innerHTML += "<style type=\"text/css\"> a { color: blue; } </style>";
				doc.body.style.margin = "0";
				doc.body.style.padding = "0";
				doc.body.style.fontFamily = "Verdana, Arial, Helvetica, sans-serif";
				doc.body.style.fontSize = "80%";
				doc.body.innerHTML = this.data;
				this._panel._editorWnd = this.contentWindow;
				doc._wnd = this._wnd;
				doc._docWnd = this.contentWindow;
				doc._panel = this._panel;
				new EventListener(doc, "keydown", this._panel.onRichTextKey);
				new EventListener(doc, "keydown", function(evn) {
						if (evn.ctrlKey && !evn.altKey && (evn.keyCode == 13)) { // Ctrl-Enter
							this._wnd._tmp = this._panel.form._updateAction;
							this._wnd._tmp.entityView = this._panel._loadedEntityView;
							this._wnd.setTimeout(function() {
									// needed for Firefox 2.0.0.11
									this.focus();
									this._tmp.perform();
									this._tmp = null;
								}, 1);
							return EventListener.cancelEvent(evn);
						}
						else if (evn.keyCode == 27) { // ESC
							this._wnd._tmp = evn;
							this._wnd.setTimeout(function() {
									// needed for Firefox 2.0.0.11
									this.focus();
									Doc(this.document).handleKeyEvent(this._tmp);
									this._tmp = null;
								}, 1);
						}
					});
				new EventListener(doc, "focus", function(evn) {
						if (this._wnd._tmpHideTimerId) {
							this._wnd.clearTimeout(this._wnd._tmpHideTimerId);
							this._wnd._tmpHideTimerId = null;
						}
						this._panel._editorWnd = this._docWnd;
						this._panel.richtextToolbar.show();
					});
				new EventListener(doc, "blur", function(evn) {
						this._wnd._tmpHide = this._panel.richtextToolbar;
						if (this._wnd._tmpHideTimerId)
							this._wnd.clearTimeout(this._wnd._tmpHideTimerId);
						this._wnd._tmpHideTimerId = this._wnd.setTimeout(function() {
								this._tmpHide.hide();
								this._tmpHide = null;
							}, 500);
					});
				if (this._panel.show) {
					doc.designMode = "on";
					if (browser.isGeko)
						doc.execCommand("styleWithCSS", false, false);
					if (this._select) {
						doc.execCommand("selectAll", false, null);
						this.contentWindow.focus();
					}
				}
			});
		element.innerHTML = "";
		element.appendChild(f);
		element.iframe = f;
		element._hasInputChanged = function() {
			return this.firstChild.contentWindow.document.body.innerHTML != this._originalContent;
		}
		this._dynHeight = f;
	}
}

EditorPanel.prototype.onRichTextKey = function(evn) {
	if (evn.ctrlKey && evn.shiftKey) {
		var doc = this;
		if (!doc.execCommand)
			doc = this.ownerDocument;
		if (evn.keyCode == 66) // Ctrl-B
			doc.execCommand("bold", false, null);
		else if (evn.keyCode == 73) // Ctrl-I
			doc.execCommand("italic", false, null);
		else if (evn.keyCode == 85) // Ctrl-U
			doc.execCommand("underline", false, null);
		else if (evn.keyCode == 75) // Ctrl-K
			doc.execCommand("strikethrough", false, null);
		else if (evn.keyCode == 76) // Ctrl-L
			doc.execCommand("createlink", false, "#");
		else if (evn.keyCode == 68) // Ctrl-D
			doc.execCommand("subscript", false, null);
		else if (evn.keyCode == 80) // Ctrl-P
			doc.execCommand("superscript", false, null);
		else if (evn.keyCode == 82) // Ctrl-R
			doc.execCommand("removeFormat", false, null);
		else if (evn.keyCode == 78) // Ctrl-N
			doc.execCommand("unlink", false, null);
		else
			doc = null;
		if (doc != null)
			return EventListener.cancelEvent(evn);
	}
}

EditorPanel.prototype.getInputValue = function(path) {
	var inputId;
	var elements = this._editor.getElementsByTagName("*");
	for (var i = 0; i < elements.length; ++i) {
		var e = elements[i];
		if (e.name && (e.name.indexOf("path_") == 0) && (e.value == path)) {
			inputId = "content_" + e.name.substring(5);
			break;
		}
	}
	if (!inputId)
		return null;
	for (var i = 0; i < elements.length; ++i) {
		var e = elements[i];
		if (e.name == inputId)
			return (e.value)?e.value:e.innerHTML;
	}
	return null;
}

EditorPanel.prototype.ed_resizeImage = function(input, evn, path) {
	var width = this.getInputValue("@preview-width");
	var height = this.getInputValue("@preview-height");
	var img = this._entityView.dom.element.firstChild;
	if (!width || (width == "") || (width.indexOf("px") > 0) || (width.indexOf("%") > 0))
		img.style.width = width;
	if (!height || (height == "") || (height.indexOf("px") > 0) || (height.indexOf("%") > 0))
		img.style.height = height;
}

function TemplatePanel(doc) {
	TemplatePanel._super.call(this, "tmpl", doc);
	this.frame = this.doc.doc.createElement("iframe");
	this.frame.setAttribute("height", "auto");
	this.frame.setAttribute("width", "99%");
	this.frame.setAttribute("frameborder", "0", false);
	this.frame.setAttribute("vspace", "0", false);
	this.frame.style.marginLeft = "0.5%";
	this.frame.style.marginRight = "0.5%";
	this.element.appendChild(this.frame);
}
Object.extend("TemplatePanel", "WindowPanel");

TemplatePanel.prototype.setEntityView = function(entityView) {
	this._entityView = entityView;
	if (this.isOpen && this._entityView)
		this.loadEntity();
}

TemplatePanel.prototype.open = function() {
	TemplatePanel._super.prototype.open.call(this);
	if (this._entityView)
		this.loadEntity();
}

TemplatePanel.prototype.loadEntity = function() {
	if (!this._entityView)
		return;
	if (this._entityView != this._loadedEntityView) {
		this.header.innerHTML = "<span>Insert into</span> " + this._entityView.getActiveEntityPath();
		var self = this;
		this.frame.src = BasePath.get() + "/livcos.org/web/editor/Templates.view?objId="
			+ this._entityView.objId + "&id=" + this._entityView.id;
		this._loadedEntityView = this._entityView;
	}
}

function RichtextToolbar(dom) {
	this.dom = dom;
	this.dom.firstChild && this.dom.removeChild(this.dom.firstChild);
	this.hide();
}

RichtextToolbar.prototype.show = function() {
	this.dom.style.display = "block";
}

RichtextToolbar.prototype.hide = function() {
	this.dom.style.display = "none";
}

RichtextToolbar.prototype.addButton = function(title, stripPos, cmd) {
	var doc = this.dom.ownerDocument;
	var b = doc.createElement("img");
	b.src = BasePath.get() + EDIT_IMAGE_BASE + "/c.gif";
	b.className = "ed_toolbar";
	b.style.backgroundImage = "url('" + BasePath.get() + EDIT_IMAGE_BASE + "/richtext/toolbar.gif')";
	b._tb = this;
	b._cmd = cmd;
	b.onclick = function() {
		this._tb && this._tb.execCmd(this._cmd);
	}
	b.alt = title;
	b.title = title;
	b.style.backgroundPosition = "0px -" + (stripPos * 16) + "px";
	this.dom.appendChild(b);
}
